package com.yanmaohu.nikita.utility;

import com.yanmaohu.nikita.configuration.Version;

/**
 * @author Bright Lee
 */
public final class ConfigurationUtility {

    public static String trimRootPackage(String rootPackage) throws Exception {
        if (rootPackage == null || rootPackage.isBlank()) {
            return ValueUtility.DEFAULT_ROOT_PACKAGE;
        }
        StringBuilder buf = new StringBuilder(rootPackage.length());
        String[] a = rootPackage.split("\\.");
        for (int i = 0; i < a.length; i++) {
            String s = trimPackageNodeName(a[i]);
            buf.append(s);
            if (i < a.length - 1) {
                buf.append('.');
            }
        }
        return buf.toString();
    }

    private static String trimPackageNodeName(String packageName) throws Exception {
        if (packageName == null || packageName.isBlank()) {
            throw new Exception("The package node name cannot be blank.");
        }
        packageName = packageName.trim();
        char c = packageName.charAt(0);
        if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_')) {
            throw new Exception("The first letter of the package node name must be an English letter or an underscore.");
        }
        for (int i = 1; i < packageName.length(); i++) {
            c = packageName.charAt(i);
            if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_')) {
                throw new Exception("All characters after the first letter of the package node name must be composed of English letter, digital or underscore.");
            }
        }
        return packageName;
    }

    public static Version parseVersion(String version) throws Exception {
        if (version == null || version.isBlank()) {
            return new Version(1, 0, 0);
        }
        int major = 1;
        int minor = 0;
        int patch = 0;
        String[] a = version.split("\\.");
        if (a.length == 1) {
            major = parseMajorVersion(a[0]);
            minor = 0;
            patch = 0;
        } else if (a.length == 2) {
            major = parseMajorVersion(a[0]);
            minor = parseMinorVersion(a[1]);
            patch = 0;
        } else if (a.length == 3) {
            major = parseMajorVersion(a[0]);
            minor = parseMinorVersion(a[1]);
            patch = parsePatchVersion(a[2]);
        } else {
            throw new Exception("The format of the version number is major.minor.patch, input string is " + version);
        }
        return new Version(major, minor, patch);
    }

    private static int parseMajorVersion(String value) throws Exception {
        try {
            value = value.trim();
            int major = Integer.parseInt(value);
            if (major < 1) {
                throw new Exception(value);
            }
            return major;
        } catch (Exception e) {
            throw new Exception("Major version must be an integer greater than 1.", e);
        }
    }

    private static int parseMinorVersion(String value) throws Exception {
        try {
            value = value.trim();
            int minor = Integer.parseInt(value);
            if (minor < 0) {
                throw new Exception(value);
            }
            return minor;
        } catch (Exception e) {
            throw new Exception("Minor version must be a non negative integer.", e);
        }
    }

    private static int parsePatchVersion(String value) throws Exception {
        try {
            value = value.trim();
            int patch = Integer.parseInt(value);
            if (patch < 0) {
                throw new Exception(value);
            }
            return patch;
        } catch (Exception e) {
            throw new Exception("Patch version must be a non negative integer.", e);
        }
    }

    public static String trimVersion(String version) throws Exception {
        Version v = parseVersion(version);
        return v.getMajorVersion() + "." + v.getMinorVersion() + "." + v.getPatchVersion();
    }

}
